import yaml
from apscheduler.schedulers.blocking import BlockingScheduler
from loguru import logger
import os
import yaml
import importlib
import functools
from notify import send_sync_notification, send_error_alert


def load_config():
    """
    加载配置文件
    """
    current_dir = os.path.dirname(os.path.abspath(__file__))
    config_path = os.path.join(os.path.dirname(current_dir), 'config', 'config.yaml')
    with open(config_path, encoding='utf-8') as f:
        return yaml.safe_load(f)


def setup_logging(config):
    """
    设置日志配置
    """
    logs_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), '../logs'))
    os.makedirs(logs_dir, exist_ok=True)
    log_path = os.path.join(logs_dir, 'scheduler.log')
    
    # 获取日志配置
    log_config = config.get('global', {}).get('log', {})
    level = log_config.get('level', 'INFO')
    rotation = log_config.get('rotation', '10 MB')
    retention = log_config.get('retention', '30 days')
    
    logger.remove()
    logger.add(
        log_path, 
        rotation=rotation, 
        retention=retention, 
        encoding="utf-8", 
        enqueue=True, 
        backtrace=True, 
        diagnose=True,
        level=level
    )
    logger.add(lambda msg: print(msg, end=""), level="INFO")


def create_handler_wrapper(handler_id, handler_config, global_config):
    """
    创建Handler包装器函数
    
    Args:
        handler_id: Handler ID
        handler_config: Handler配置
        global_config: 全局配置
    
    Returns:
        callable: 包装后的Handler函数
    """
    def wrapper():
        handler_name = handler_config['name']
        module_name = handler_config['handler']['module']
        function_name = handler_config['handler']['function']
        
        try:
            # 动态导入模块
            module = importlib.import_module(module_name)
            handler_func = getattr(module, function_name)
            
            # 准备参数（不再传递数据库配置）
            parameters = handler_config.get('parameters', {})
            
            logger.info(f"[{handler_name}] 开始执行任务")
            
            # 执行Handler函数
            result = handler_func(**parameters)
            
            logger.info(f"[{handler_name}] 任务执行完成")
            
            # 发送通知
            if global_config.get('notification', {}).get('wechat_work', {}).get('enabled', False):
                try:
                    if result.get('error_count', 0) == 0:
                        # 成功通知
                        send_sync_notification(
                            task_name=handler_name,
                            success_count=result.get('success_count', 0)
                        )
                    else:
                        # 错误告警
                        send_error_alert(
                            task_name=handler_name,
                            error_message=f"任务执行出现 {result.get('error_count', 0)} 个错误",
                            error_details=result.get('error_details', [])
                        )
                except Exception as notify_error:
                    logger.warning(f"[{handler_name}] 发送通知失败: {notify_error}")
            
        except Exception as e:
            logger.exception(f"[{handler_name}] 任务执行失败: {e}")
            
            # 发送错误通知
            if global_config.get('notification', {}).get('wechat_work', {}).get('enabled', False):
                try:
                    send_error_alert(
                        task_name=handler_name,
                        error_message=f"任务执行异常: {str(e)}",
                        error_details=[str(e)]
                    )
                except Exception as notify_error:
                    logger.warning(f"[{handler_name}] 发送错误通知失败: {notify_error}")
    
    return wrapper


def parse_cron_expression(cron_expr):
    """
    解析cron表达式
    
    Args:
        cron_expr: cron表达式字符串
        
    Returns:
        dict: 包含minute, hour, day, month, day_of_week的字典
    """
    cron_parts = cron_expr.split()
    return {
        'minute': cron_parts[0] if len(cron_parts) > 0 else '0',
        'hour': cron_parts[1] if len(cron_parts) > 1 else '*',
        'day': cron_parts[2] if len(cron_parts) > 2 else '*',
        'month': cron_parts[3] if len(cron_parts) > 3 else '*',
        'day_of_week': cron_parts[4] if len(cron_parts) > 4 else '*'
    }


def main():
    """
    主函数，启动多handler调度器
    """
    config = load_config()
    setup_logging(config)
    
    scheduler = BlockingScheduler()
    handlers_config = config.get('handlers', {})
    
    if not handlers_config:
        logger.warning("未找到handler配置，调度器将不会添加任何任务")
        return
    
    # 添加所有启用的handler
    active_handlers = 0
    for handler_id, handler_config in handlers_config.items():
        if not handler_config.get('enabled', True):
            logger.info(f"跳过已禁用的handler: {handler_id}")
            continue
            
        handler_name = handler_config.get('name', handler_id)
        cron_expr = handler_config.get('schedule', {}).get('cron', '0 * * * *')
        
        try:
            # 解析cron表达式
            cron_params = parse_cron_expression(cron_expr)
            
            # 创建handler包装器
            handler_wrapper = create_handler_wrapper(handler_id, handler_config, config)
            
            # 添加到调度器
            scheduler.add_job(
                handler_wrapper,
                'cron',
                id=handler_id,
                name=handler_name,
                **cron_params
            )
            
            active_handlers += 1
            logger.info(f"已添加handler: {handler_name} (ID: {handler_id}), 调度: {cron_expr}")
            
        except Exception as e:
            logger.error(f"添加handler失败: {handler_id}, 错误: {str(e)}")
    
    if active_handlers == 0:
        logger.warning("没有启用的handler，调度器退出")
        return
    
    logger.info(f"调度器启动成功，共加载 {active_handlers} 个handler")
    
    try:
        scheduler.start()
    except (KeyboardInterrupt, SystemExit):
        logger.info("调度器已停止")
    except Exception as e:
        logger.exception(f"调度器运行异常: {str(e)}")

if __name__ == '__main__':
    main()
